package com.zhuiyun.project.api.system.dict.service.Impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.zhuiyun.project.api.system.dict.entity.DictData;
import com.zhuiyun.project.api.system.dict.entity.DictType;
import com.zhuiyun.project.api.system.dict.mapper.DictDataMapper;
import com.zhuiyun.project.api.system.dict.mapper.DictTypeMapper;
import com.zhuiyun.project.api.system.dict.service.DictTypeService;
import com.zhuiyun.project.common.errorCode.EmErrorCode;
import com.zhuiyun.project.common.response.CommonResult;
import com.zhuiyun.project.utils.DictUtils;
import com.zhuiyun.project.utils.ObjectUtils;
import com.zhuiyun.project.utils.RedisUtil;
import com.zhuiyun.project.utils.StringUtils;
import com.zhuiyun.project.utils.pageUtil.PageRequest;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.PostConstruct;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @ClassName DictServiceImpl
 * @Description TODO 字典类型接口实现类
 * @Author gpd
 * @Date 2023-06-15 下午 04:18
 **/
@Service
public class DictTypeServiceImpl extends ServiceImpl<DictTypeMapper, DictType> implements DictTypeService {

    @Autowired
    DictTypeMapper dictTypeMapper;

    @Autowired
    DictDataMapper dictDataMapper;

    /**
    * @Description 项目启动时，初始化字典到缓存
    * @Author lzy
    * @Date 2023/7/25 16:20
    * @Return void
    */
    @PostConstruct
    public void init()
    {
        loadingDictCache();
    }

    /**
     * @Author gpd
     * @Description 查询字典管理类型
     * @Date 2023-06-15 下午 05:05
     * @Return PageResult，CommonResult

     */
    @Override
    public IPage<DictType> listType(PageRequest pageRequest, DictType dictType) {
        // 创建查询构造器
        QueryWrapper<DictType> dictTypeEntityQueryWrapper = new QueryWrapper<>();
        // 设置查询条件
        if (dictType.getDictType() != null) {
            dictTypeEntityQueryWrapper.eq("dict_type", dictType.getDictType());
        }
        if (dictType.getDictName() != null) {
            dictTypeEntityQueryWrapper.eq("dict_name", dictType.getDictName());
        }
        if (dictType.getStatus() != null) {
            dictTypeEntityQueryWrapper.eq("status", dictType.getStatus());
        }
        if (dictType.getParams().size() != 0 && ObjectUtils.isNotEmpty(dictType.getParams())) {
            // 获取前端传来的时间
            Object beginTimeObj = dictType.getParams().get("beginTime");
            Object endTimeObj = dictType.getParams().get("endTime");
            // 转换为string类型
            String beginTimeStr = (String) beginTimeObj;
            String endTimeStr = (String) endTimeObj;
            // 再将string类型的转为LocalDate类型
            LocalDate beginTime = LocalDate.parse(beginTimeStr);
            LocalDate endTime = LocalDate.parse(endTimeStr);
            // 如果开始时间和结束时间一致
            if (beginTimeStr.equals(endTimeStr)) {
                // 设置开始时间 那天的00：00
                LocalDateTime startDateTime = beginTime.atStartOfDay();
                // 设置结束时间 那天的23：59：59...
                LocalDateTime endDateTime = beginTime.atTime(LocalTime.MAX);
                dictTypeEntityQueryWrapper.between("create_time", startDateTime, endDateTime);
            } else {
                // 大于等于某天 xxxx年-xx月-xx天
                dictTypeEntityQueryWrapper.ge("create_time", beginTime);
                // 小于等于某天 xxxx年-xx月-xx天
                dictTypeEntityQueryWrapper.le("create_time", endTime);
            }
        }
        // 设置分页规则
        Page<DictType> dictTypeEntityPage = new Page<>(pageRequest.getPageNum(), pageRequest.getPageSize());
        // 根据分页规则和条件进行查询
        IPage<DictType> dictTypeEntityIPage = dictTypeMapper.selectPage(dictTypeEntityPage, dictTypeEntityQueryWrapper);
        return dictTypeEntityIPage;
    }

    /**
     * @Author gpd
     * @Description 查询字典类型详细(用于字段类型新增和修改)
     * @Date 2023-06-17 上午 09:54
     * @Return CommonResult

     */
    @Override
    public DictType getType(Long dictId) {
        return dictTypeMapper.selectById(dictId);
    }

    /**
     * @Author gpd
     * @Description 新增
     * @Date 2023-06-17 上午 09:45
     * @Return com.zhuiyun.project.common.response.CommonResult

     */
    @Override
    public Integer addDictType(DictType dictType) {
        int row = dictTypeMapper.insertDictType(dictType);
        // 新增成功后，把新增的字典类型名称存进redis缓存中
        if(row>0){
            RedisUtil.setDictCache(dictType.getDictType(),null);
        }
        return row;
    }

    /**
     * @Author gpd
     * @Description 字段新增查询校验字典类型称是否唯一
     * @Date 2023-06-17 上午 10:40
     * @Return boolean

     */
    @Override
    public boolean checkDictTypeUnique(DictType dictTypeEntity) {
        // 判断前端传回来的数组中的dictId是否为空 如果为空则给dictId一个-1L的值，有值则赋给dictId
        Long dictId = StringUtils.isNull(dictTypeEntity.getDictId()) ? -1L : dictTypeEntity.getDictId();
        // 调用mapper 方法 使用longValue()方法对前一步的dictId（long对象）进行拆箱的操作，转换为long类型（Long是一个包装类型，表示一个64位有符号整型数，不能直接进行运算）
        // 调用longValue()方法如果long对象值为null会抛出NullPointerException异常 但上面对dictId进行赋值避免了这种问题的发生
        DictType dictType = dictTypeMapper.checkDictTypeUnique(dictTypeEntity.getDictType());
        // 先比较这个dictType实体类如果为空直接返回false不去执行右边的判断
        if(StringUtils.isNotNull(dictType) && dictType.getDictId().longValue()!=dictId.longValue()){
            return false;
        }
        else{
            return true;
        }

    }

    /**
     * @Author gpd
     * @Description 修改字典类型
     * @Date 2023-06-19 上午 08:36
     * @Return CommonResult

     */
    @Override
    public Integer updateDictType(DictType dictTypeEntity) {
        // 根据前端传回来的值查询数据库
        DictType dictType = dictTypeMapper.selectDictTypeById(dictTypeEntity.getDictId());
        // 同步修改字典列表中的字典类型名称（字段）
        dictDataMapper.updateDictDataType(dictType.getDictType(), dictTypeEntity.getDictType());
        // 修改字典类型信息
        int row = dictTypeMapper.updateDictType(dictTypeEntity);
        if(row>0){
            List<DictData> dictDataEntities = dictDataMapper.selectDictDataByType(dictTypeEntity.getDictType());
            RedisUtil.setDictCache(dictTypeEntity.getDictType(),dictDataEntities);
        }
        return row;
    }

    /**
     * @Author gpd
     * @Description 删除字典类型
     * @Date 2023-06-19 上午 09:56
     * @Return CommonResult

     */
    @Override
    public CommonResult deleteDictType(Long[] dictIds){
        if(ObjectUtils.isNotEmpty(dictIds)) {
            for (Long dictId : dictIds){
                DictType dictType = dictTypeMapper.selectById(dictId);
                // 如果查询的结果大于0说明该字典类型下面有字典详情
                if(dictDataMapper.countDictDataByType(dictType.getDictType())>0){
                    return CommonResult.error(EmErrorCode.DELETE_ERROR+"%1$s已分配,不能删除"+dictType.getDictName());
                }
                else{
                    // 删除字典类型
                    int row = dictTypeMapper.deleteDictTypeById(dictId);
                    // 清空redis中的缓存
                    RedisUtil.removeDictCache(dictType.getDictType());
                    if(row>0){
                        return CommonResult.ok(EmErrorCode.DELETE_OK);
                    }
                    else{
                        return CommonResult.error(EmErrorCode.DELETE_ERROR);
                    }
                }
            }
        }else{
            return CommonResult.error(EmErrorCode.DELETE_ERROR);
        }
        return null;
    }

    /**
     * @Author gpd
     * @Description 刷新字典缓存
     * @Date 2023-06-19 上午 11:13
     * @Return CommonResult

     */
    @Override
    public CommonResult refreshCache() {
        // 删除redis中的字典缓存
        RedisUtil.clearDictCache();
        DictData dictData = new DictData();
        dictData.setStatus("0");
        // 重新查询数据库中的字典类型信息并把它存进redis中
        Map<String, List<DictData>> dictDataMap = dictDataMapper.selectDictDataList(dictData).stream().collect(Collectors.groupingBy(DictData::getDictType));
        for (Map.Entry<String, List<DictData>> entry : dictDataMap.entrySet())
        {
            RedisUtil.setDictCache(entry.getKey(), entry.getValue().stream().sorted(Comparator.comparing(DictData::getDictSort)).collect(Collectors.toList()));
        }
        return CommonResult.ok();
    }

    /**
     * @Author gpd
     * @Description 获取字典选择框列表
     * @Date 2023-06-19 下午 02:30
     * @Return CommonResult

     */
    @Override
    public List<DictType> optionselect() {
        return dictTypeMapper.selectDictTypeAll();
    }

    /**
     * @Author gpd
     * @Description 根据前端传回的值查询种植作物类型
     * @Date 2023-06-26 上午 11:35
     * @Return CommonResult

     */
    @Override
    public CommonResult getPlantType(String dictType) {
        Object o =RedisUtil.get("plantTypeList");
        if(o==null){
            List<DictType> dictTypeList = dictTypeMapper.getPlantType(dictType);
            for (DictType dictTypeEntity : dictTypeList) {
                dictTypeEntity.setChildren(dictDataMapper.selectDictDataByType(dictTypeEntity.getDictType()));
            }
            RedisUtil.set("plantTypeList", dictTypeList);
            return CommonResult.ok(dictTypeList);
        }
        return CommonResult.ok(o);
    }

    /**
    * @Description 加载字典缓存数据
    * @Author lzy
    * @Date 2023/7/25 16:17
    * @Return void
    */
    @Override
    public void loadingDictCache()
    {
        DictData dictData = new DictData();
        dictData.setStatus("0");
        Map<String, List<DictData>> dictDataMap = dictDataMapper.selectDictDataList(dictData).stream().collect(Collectors.groupingBy(DictData::getDictType));
        for (Map.Entry<String, List<DictData>> entry : dictDataMap.entrySet())
        {
            DictUtils.setDictCache(entry.getKey(), entry.getValue().stream().sorted(Comparator.comparing(DictData::getDictSort)).collect(Collectors.toList()));
        }
    }

    /**
     * @Author gpd
     * @Description 获取教练类型
     * @Date 2023-08-23 上午 11:34
     * @Return CommonResult

     */
    @Override
    public List<DictType> getCoachDictType() {
        QueryWrapper<DictType> queryWrapper = new QueryWrapper<>();
        queryWrapper.like("dict_type","coach_excel_");
        return dictTypeMapper.selectList(queryWrapper);
    }


}
